/*
 * anima/object.hh - Object and reference data types.
 * Copyright (C) 2007  Mikhail Vorozhtsov
 * See the LICENSE section of the README file for details.
 */

/* $Id$ */

#ifndef HEADER_ANIMA_OBJECT_HH
#define HEADER_ANIMA_OBJECT_HH

#include ANIMA_ARCH_HEADER (object.hh)
#include ANIMA_ARCH_HEADER (mm.hh)
#include HEADER (anima,atomic.hh)

START_NAMESPACE (anima)

class mm;

struct object_t : public ANIMA_ARCH::object_t
{
  friend class mm;

public:
  enum state_t
  {
    STATE_NONE = 0,
    STATE_ACTIVE = 1,
    STATE_DEACTIVATING = 2,
    STATE_INACTIVE = 4,
    STATE_DEALLOCATING = 8
  };

public:
  static const u64_t SERIAL_NONE = -U64 (1);

public:
  u64_t serial : 64 - BITS + ANIMA_ARCH::mm::PAGE_BITS;

protected:
  u64_t paddr;
  atomic_t<state_t> state;
  rw_lock64_t usage_lock;
  atomic64_t refs_cnt;
};

template <typename T>
union ref_t
{
  struct
    {
      u64_t addr : object_t::BITS - ANIMA_ARCH::mm::PAGE_BITS;
      u64_t serial : 64 - object_t::BITS + ANIMA_ARCH::mm::PAGE_BITS;
    };
  u64_t raw;

  UTILS_RAW_ZERO (ref_t, u64_t)

  INLINE
  ref_t (T *obj)
  {
    set (obj);
  }

  INLINE
  ref_t &
  set (T *obj)
  {
    addr = ((u64_t) obj >> ANIMA_ARCH::mm::PAGE_BITS);
    serial = obj->serial;
    return *this;
  }

  INLINE
  T *
  get ()
  {
    return (T *) (object_t::BASE
                  + ((u64_t) addr << ANIMA_ARCH::mm::PAGE_BITS));
  }

  INLINE
  ref_t &
  null ()
  {
    raw = 0;
    return *this;
  }

  INLINE
  bool
  null_p ()
  {
    return raw == 0;
  }
};

struct cpu_t;
struct space_t;
struct thread_t;

typedef ref_t<cpu_t> cpu_ref_t;
typedef ref_t<space_t> space_ref_t;
typedef ref_t<thread_t> thread_ref_t;

END_NAMESPACE

#endif /* HEADER_ANIMA_OBJECT_HH */

